﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.Collections;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Resources;
using System.Windows;
using System.Windows.Markup;

namespace NETXPF.WPF.PropertyList
{
    public class EnumDisplayer : DependencyObject, IValueConverter
    {
        private Dictionary<object, EnumDisplayEntry> displayValues;

        public EnumDisplayer()
        {
        }

        private void BuildDisplayNames(Type type)
        {
            this.displayValues = new Dictionary<object, EnumDisplayEntry>();

            var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
            foreach (var field in fields)
            {
                DisplayStringAttribute[] a = (DisplayStringAttribute[])
                                            field.GetCustomAttributes(typeof(DisplayStringAttribute), false);

                string displayString = GetDisplayStringValue(type, a);
                object enumValue = field.GetValue(null);

                if (displayString == null)
                {
                    displayString = GetBackupDisplayStringValue(type, enumValue);
                }
                if (displayString != null)
                {
                    EnumDisplayEntry ede = new EnumDisplayEntry { EnumValue = enumValue, DisplayString = displayString };
                    displayValues.Add(enumValue, ede);
                }
            }
        }

        object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            BuildDisplayNames(value.GetType());
            if (parameter != null && parameter.Equals("AllValues"))
            {
                return displayValues.Values;
            }
            return displayValues[value];
        }

        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                return null;
            }
            return ((EnumDisplayEntry)value).EnumValue;
        }

        private string GetDisplayStringValue(Type t, DisplayStringAttribute[] a)
        {
            if (a == null || a.Length == 0) return null;
            DisplayStringAttribute dsa = a[0];
            if (!string.IsNullOrEmpty(dsa.ResourceKey))
            {
                ResourceManager rm = new ResourceManager(t);
                return rm.GetString(dsa.ResourceKey);
            }
            return dsa.Value;
        }

        private string GetBackupDisplayStringValue(Type t, object enumValue)
        {
            return Enum.GetName(t, enumValue);
        }
    }

    public class EnumDisplayEntry
    {
        public object EnumValue { get; set; }
        public string DisplayString { get; set; }
        public override string ToString()
        {
            return DisplayString;
        }
        public override bool Equals(object obj)
        {
            if (obj is EnumDisplayEntry)
            {
                return ((EnumDisplayEntry)obj).EnumValue.Equals(EnumValue);
            }
            return base.Equals(obj);
        }
        public override int GetHashCode()
        {
            return EnumValue.GetHashCode();
        }
    }

    [AttributeUsage(AttributeTargets.Field)]
    public sealed class DisplayStringAttribute : Attribute
    {
        private readonly string value;
        public string Value
        {
            get { return value; }
        }

        public string ResourceKey { get; set; }

        public DisplayStringAttribute(string v)
        {
            this.value = v;
        }

        public DisplayStringAttribute()
        {
        }
    }
}
